#pragma once 
#include <iostream>
#include <string>
#include <functional>
#include <pthread.h>

// //1、非类模板版本的封装
// //设计方的视角
// //typedef std::function<void()> func_t;
// using func_t = std::function<void()>;

// //将线程对象化
// class Thread
// {
// public:
//     Thread(func_t func, const std::string &threadname)
//     :_tid(0), _threadname(threadname), _isrunning(false), _func(func)
//     {}

//     static void *ThreadRoutine(void *args)//类内方法,会默认携带隐含参数this指针
//     {
//         //(void)args;//使用一下，仅仅是为了防止编译器有告警
//         Thread *ts = static_cast<Thread *>(args);
//         ts->_func();
//         return nullptr;
//     }

//     bool Start()
//     {
//         int n = pthread_create(&_tid, nullptr, ThreadRoutine, this);//这里this指针，把当前对象传进来
//         if(n == 0)
//         {
//             _isrunning = true;
//             return true;
//         }
//         else return false;
//     }

//     bool Join()
//     {
//         if(!_isrunning) return true;
//         int n = pthread_join(_tid, nullptr);
//         if(n == 0)
//         {
//             _isrunning = false;
//             return true;
//         }
//         return false;
//     }

//     std::string ThreadName()
//     {
//         return _threadname;
//     }

//     bool IsRunning()
//     {
//         return _isrunning;
//     }

//     ~Thread()
//     {}

// private:
//     pthread_t _tid;
//     std::string _threadname;
//     bool _isrunning;
//     func_t _func;
    
// };


//2.带模板的封装，方便线程传参和线程返回值
//设计方的视角
//typedef std::function<void()> func_t;
template<class T>//T是为了线程传参
using func_t = std::function<void(T&)>;

//将线程对象化
template<class T>
class Thread
{
public:
    Thread(const std::string &threadname, func_t<T> func, T &data)//创建一个线程默认要传入线程名，要执行的函数，和数据
    :_tid(0), _threadname(threadname), _isrunning(false), _func(func), _data(data)
    {}

    static void *ThreadRoutine(void *args)//类内方法,会默认携带隐含参数this指针
    {
        //(void)args;//使用一下，仅仅是为了防止编译器有告警
        Thread *ts = static_cast<Thread *>(args);
        ts->_func(ts->_data);
        return nullptr;
    }

    bool Start()
    {
        int n = pthread_create(&_tid, nullptr, ThreadRoutine, this);//这里this指针，把当前对象传进来
        if(n == 0)
        {
            _isrunning = true;
            return true;
        }
        else return false;
    }

    bool Join()
    {
        if(!_isrunning) return true;
        int n = pthread_join(_tid, nullptr);
        if(n == 0)
        {
            _isrunning = false;
            return true;
        }
        return false;
    }

    std::string ThreadName()
    {
        return _threadname;
    }

    bool IsRunning()
    {
        return _isrunning;
    }

    ~Thread()
    {}

private:
    pthread_t _tid;
    std::string _threadname;
    bool _isrunning;
    func_t<T> _func;
    T _data;//线程返回值
    
};